// Package dbsvc
// @Author: zhangdi
package dbsvc

import (
	"errors"
	"fmt"
	"server/application/constant/enums"
	"server/application/constant/syscnt"
	"server/application/db/system/columns"
	"server/application/db/system/dbdto"
	"server/application/db/system/entity"
	"server/application/db/system/repository"
	"server/application/dto"
	"server/pkg/myexcel"
	"server/pkg/mynum"
	"server/pkg/utils"
	"server/pkg/where"
	"server/setting"
	"strconv"
	"strings"
	"time"
)

// SysUserCreate 创建
func SysUserCreate(dtoCreate *dbdto.SysUserCreate) (*dbdto.SysUserInfo, error) {
	info, _ := SysUserFindOne(where.Format(where.Opt(columns.SysUserUsername, "=", dtoCreate.Username)))
	if info.ID > 0 {
		return nil, errors.New("该用户名已存在，换一个吧")
	}
	dtoCreate.Password = utils.MD5(dtoCreate.Password)
	return repository.Create[
		entity.SysUser, dbdto.SysUserCreate, dbdto.SysUserInfo,
	](dtoCreate)
}

// SysUserFindOne 查找
func SysUserFindOne(wheres []*where.Condition) (*dbdto.SysUserInfo, error) {
	return repository.FindOne[
		entity.SysUser, dbdto.SysUserInfo,
	](wheres, false)
}

func SysUserFindOneById(id uint) (*dbdto.SysUserInfo, error) {
	wheres := where.FormatOne("id", "=", id)
	return repository.FindOne[
		entity.SysUser, dbdto.SysUserInfo,
	](wheres, false)
}

// SysUserFindList 查找列表
func SysUserFindList(wheres []*where.Condition, extra *where.Extra) ([]*dbdto.SysUserInfo, error) {
	return repository.FindList[
		entity.SysUser, dbdto.SysUserInfo](wheres, extra, false)
}

// SysUserSearch 搜索
func SysUserSearch(wheres []*where.Condition, extra *where.Extra) ([]*dbdto.SysUserInfo, int64) {
	total, err := SysUserGetTotal(wheres)
	list := make([]*dbdto.SysUserInfo, 0)
	if err != nil || total <= 0 {
		return list, 0
	}
	list, err = SysUserFindList(wheres, extra)
	return list, total
}

// SysUserUpdate 更新，可手动传入字段或修改规则，传入哪个字段修改哪个
func SysUserUpdate(wheres []*where.Condition, dtoUpdate *dbdto.SysUserUpdate, columnsCfg ...string) error {
	if dtoUpdate.Password != "" {
		dtoUpdate.Password = utils.MD5(dtoUpdate.Password)
	}
	return repository.Update[
		entity.SysUser, dbdto.SysUserUpdate](wheres, dtoUpdate, columnsCfg...)
}

// SysUserDelete 删除（deleted_at存在则是软删除）
func SysUserDelete(wheres []*where.Condition) error {
	return repository.Delete[entity.SysUser](wheres, setting.UseSoftDelete)
}

// SysUserGetTotal 获取总数
func SysUserGetTotal(wheres []*where.Condition) (int64, error) {
	return repository.GetTotal[entity.SysUser](wheres)
}

// SysUserGetRoleIds 获取一个用户的角色列表,返回uint切片
func SysUserGetRoleIds(uid uint) []uint {
	info, err := SysUserFindOne(where.Format(where.Opt(columns.SysUserID, "=", uid)))
	if err != nil {
		return nil
	}
	if info.ID <= 0 {
		return nil
	}
	arr := strings.Split(info.RoleIds, ",")
	listRoleId := make([]uint, 0)
	for _, item := range arr {
		roleId, err := strconv.Atoi(item)
		if err != nil {
			continue
		}

		listRoleId = append(listRoleId, uint(roleId))
	}
	return listRoleId
}

// SysUserIsSuperAdmin 判断某个用户是否为超级管理员
func SysUserIsSuperAdmin(uid uint) bool {
	roleIds := SysUserGetRoleIds(uid) //获取角色列表
	SuperStrRoleIds := strings.Split(syscnt.SuperRoleIds, ",")
	SuperRoleIds := make([]uint, 0)
	for _, roleIdStr := range SuperStrRoleIds {
		roleId, err := strconv.Atoi(roleIdStr)
		if err != nil {
			continue
		}
		SuperRoleIds = append(SuperRoleIds, uint(roleId))
	}
	//判断是否有交集，如果是则为超级角色不要二次过滤
	if mynum.HasIntersection[uint](roleIds, SuperRoleIds) {
		return true //超级管理员
	}

	return false
}

// SysUserImportData 导入excel文件
func SysUserImportData(filePath string, WhenErrorUpdate bool) (err error) {
	defer func() { //捕获异常
		if p := recover(); p != nil {
			err = fmt.Errorf("panic occurred: %v", p)
		}
	}()
	var data []dbdto.SysUserCreate
	result, err := myexcel.ParseExcel(filePath, &dbdto.SysUserCreate{})
	if err != nil {
		return err
	}
	//转成切片
	for _, item := range result {
		data = append(data, *item.(*dbdto.SysUserCreate))
	}

	//插入数据
	_, err = repository.CreateBatch[entity.SysUser, dbdto.SysUserCreate](data, WhenErrorUpdate)
	if err != nil {
		return err
	}

	return err
}

// SysUserExportData 导出数据
func SysUserExportData(params *dto.ReqSearch) (string, error) {
	total, err := SysUserGetTotal(params.Wheres)
	if err != nil {
		return "", err
	}
	if total > int64(params.Extra.PageSize) {
		return "", errors.New(fmt.Sprintf("导出总数%v大于%v,请分批导出", total, params.Extra.PageSize))
	}
	//开始构造数据并存入本地文件
	list, _ := SysUserFindList(params.Wheres, params.Extra)
	if list == nil || len(list) <= 0 {
		return "", errors.New(fmt.Sprintf("导出数据为空"))
	}
	//开始写入数据
	filePath := "uploads/export/exportSysUser_" + time.Now().Format("20060102150105") + ".xlsx"
	err = myexcel.GenStructListFile(list, &dbdto.SysUserInfo{}, filePath)
	if err != nil {
		return "", err
	}
	return filePath, nil
}

// UserLogin 用户登录
func UserLogin(dtoLogin *dto.ReqSysLogin) (*dbdto.SysUserInfo, error) {
	//md5Pwd :=utils.MD5(dtoLogin.Password)
	wheres := where.Format(
		where.OptEqual(columns.SysUserUsername, dtoLogin.Username),
		where.OptEqual(columns.SysUserPassword, dtoLogin.Password),
	)
	info, err := UserFindOne(wheres)
	if err != nil {
		return nil, err
	}
	if info == nil || info.ID <= 0 {
		return nil, errors.New("用户名或密码错误")
	}
	if info.Status == enums.StatusFail {
		return nil, errors.New("当前用户已经被禁用，请练习管理员")
	}
	return info, nil
}

// SysUserUpdatePwd 更新密码
func SysUserUpdatePwd(newPwd string, uid uint) error {
	if newPwd == "" {
		return errors.New("新密码不能为空")
	}
	err := SysUserUpdate(
		where.Format(where.Opt(columns.SysUserID, "=", uid)),
		&dbdto.SysUserUpdate{Password: utils.MD5(newPwd)},
		columns.SysUserPassword,
	)

	return err

}

// UserFindOne 查找
func UserFindOne(wheres []*where.Condition) (*dbdto.SysUserInfo, error) {
	info, err := repository.FindOne[
		entity.SysUser, dbdto.SysUserInfo,
	](wheres, false)
	if info.ID <= 0 || err != nil {
		return nil, err
	}
	return info, nil
}

func SysUserFindOneByID(uid uint) (*dbdto.SysUserInfo, error) {
	wheres := where.Format(where.Opt(columns.SysUserID, "=", uid))
	return repository.FindOne[entity.SysUser, dbdto.SysUserInfo](
		wheres, false)
}
